package com.googlecode.animator.controller
{
	
	import com.googlecode.data.IValueObject;
	import com.googlecode.animator.data.Notifications;
	import com.googlecode.data.cameras.ActualViewCameraVO;
	import com.googlecode.data.materials.MaterialVO;
	import com.googlecode.data.materials.TextMaterialVO;
	import com.googlecode.data.objects3d.CameraProxyVO;
	import com.googlecode.data.objects3d.CubeVO;
	import com.googlecode.data.objects3d.MaterialsListObject3DVO;
	import com.googlecode.data.objects3d.Object3DVO;
	import com.googlecode.data.objects3d.PlaneVO;
	import com.googlecode.data.objects3d.SingleMaterialObject3DVO;
	import com.googlecode.data.objects3d.TargetProxyVO;
	import com.googlecode.animator.events.PropertiesPanelEvent;
	import com.googlecode.animator.view.properties.types.Depth;
	import com.googlecode.animator.view.properties.types.DisplayFlatOnScreen;
	import com.googlecode.animator.view.properties.types.Height;
	import com.googlecode.animator.view.properties.types.Object3DName;
	import com.googlecode.animator.view.properties.types.RotationX;
	import com.googlecode.animator.view.properties.types.RotationY;
	import com.googlecode.animator.view.properties.types.RotationZ;
	import com.googlecode.animator.view.properties.types.StageHeight;
	import com.googlecode.animator.view.properties.types.StageWidth;
	import com.googlecode.animator.view.properties.types.Width;
	import com.googlecode.animator.view.properties.types.Xpos;
	import com.googlecode.animator.view.properties.types.Ypos;
	import com.googlecode.animator.view.properties.types.Zpos;
	import com.googlecode.animator.view.specialobjects.BillBoard;
	import com.googlecode.animator.view.specialobjects.PlaneOutlined;
	
	import flash.geom.Point;
	
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.primitives.Plane;
	import org.puremvc.as3.multicore.interfaces.INotification;
	
	/**
	 * Handles a change to an Object3D's properties. 
	 * @author USER
	 * 
	 */
	public class UpdatePropertyCommand extends BaseCommand
	{
		/**
		 * Executes command. 
		 * @param notification
		 * 
		 */
		override public function execute(notification:INotification):void
		{
			super.execute(notification);
			
			var propEvent:PropertiesPanelEvent = notification.getBody() as PropertiesPanelEvent;
			var VO:Object = propEvent.VO;
			
			var pos:Number3D = settings.getPosObject3DInScene(VO.name);
			
			if(propEvent.target is StageWidth)
			{
				settings.stageWidth = VO.stageWidth;
			}
			
			if(propEvent.target is StageHeight)
			{
				settings.stageHeight = VO.stageHeight;
			}
			
			if(propEvent.target is Object3DName)
			{
				settings.setObject3DLabel(VO.name, VO.label);
			}

			if(propEvent.target is Xpos)
			{				
				
				pos.x = VO.x;
				settings.setPosObject3D(VO.name, pos);
				cameraCheck(VO);

			}
			
			if(propEvent.target is Ypos)
			{
				pos.y = VO.y;
				settings.setPosObject3D(VO.name, pos);
				cameraCheck(VO);
			}
			
			if(propEvent.target is Zpos)
			{
				pos.z = VO.z;
				settings.setPosObject3D(VO.name, pos);
				cameraCheck(VO);
			}			
			
			if(propEvent.target is RotationX)
			{
				settings.setObject3DRotation(VO.name, "rotationX", VO.rotationX);
			}
			
			if(propEvent.target is RotationY)
			{
				settings.setObject3DRotation(VO.name, "rotationY", VO.rotationY);
			}
			
			if(propEvent.target is RotationZ)
			{
				settings.setObject3DRotation(VO.name, "rotationZ", VO.rotationZ);
			}
			
			var obj:Object;
			
			if(propEvent.target is Width)
			{	
				settings.setObject3DDimension(VO.name, "width", VO.width);
				//settings.setObject3DHeight(name, VO.height);
				if(settings.getObject3D(VO.name) is PlaneVO)
				{
					if((settings.getObject3D(VO.name) as PlaneVO).billboard)
					{
						obj  = new Object();
						obj.name = (settings.getObject3D(VO.name) as PlaneVO).name;
						obj.displayFlatOnScreen = true;
							
						handleDisplayFlatOnScreen(obj);
					}
				}
				
				sendNotification(Notifications.OBJECT3D_DIMENSION_CHANGED_MODEL, (settings.getObject3D(VO.name) as PlaneVO).name);	
			}
			
			if(propEvent.target is Height)
			{	
				settings.setObject3DDimension(VO.name, "height", VO.height);
				
				if(settings.getObject3D(VO.name) is PlaneVO)
				{
					if((settings.getObject3D(VO.name) as PlaneVO).billboard)
					{
						obj  = new Object();
						obj.name = (settings.getObject3D(VO.name) as PlaneVO).name;
						obj.displayFlatOnScreen = true;
						
						handleDisplayFlatOnScreen(obj);
					}
				}
				
				sendNotification(Notifications.OBJECT3D_DIMENSION_CHANGED_MODEL, (settings.getObject3D(VO.name) as PlaneVO).name);
			}
			
			if(propEvent.target is Depth)
			{
				settings.setObject3DDimension(VO.name, "depth", VO.depth);
			}
			
			textFieldCheck(VO);
			
			if(propEvent.target is DisplayFlatOnScreen)
			{
				handleDisplayFlatOnScreen(VO);
				settings.setDisplayFlatOnScreen(VO.name, VO.displayFlatOnScreen);
			}
			
			
		}
		
		protected function cameraCheck(obj:Object):void
		{
			var VO:Object3DVO = settings.getObject3D(obj.name);
			
			if(object3D is CameraProxyVO || object3D is TargetProxyVO)
			{
				var cameraPos:Number3D = new Number3D();
				var targetPos:Number3D = new Number3D();
				
				for each(var object3D:Object3DVO in settings.objects3D)
				{
					if(object3D is CameraProxyVO )
					{
						cameraPos.x = object3D.x;
						cameraPos.y = object3D.y;
						cameraPos.z = object3D.z;			
					}
					
					if(object3D is TargetProxyVO )
					{
						targetPos.x = object3D.x;
						targetPos.y = object3D.y;
						targetPos.z = object3D.z;
					}
					
				}
				
				for each(var camera:IValueObject in settings.cameras)
				{
					if(camera as ActualViewCameraVO)
					{
						
						settings.setPosCamera((camera as ActualViewCameraVO).name, cameraPos, targetPos); 
					}
				}
			}
		}
		
		protected function textFieldCheck(obj:Object):void
		{
			var VO:Object3DVO = settings.getObject3D(obj.name);
			var mat:MaterialVO;
			
			if(VO is SingleMaterialObject3DVO)
			{
				mat = (VO as SingleMaterialObject3DVO).material;
				
				if(mat is TextMaterialVO)
				{
					(mat as TextMaterialVO).width = getTextDimensions(VO).x;
					(mat as TextMaterialVO).height = getTextDimensions(VO).y;

					sendNotification(Notifications.UPDATE_OBJECT3D_MATERIAL_MODEL, VO);	
				}
				
				return;
			}
			
			var clone3D:Object3DVO = VO.clone() as Object3DVO;
			
			if(clone3D is MaterialsListObject3DVO)
			{
				for each(mat in (clone3D as MaterialsListObject3DVO).materialsList)
				{
					if(mat is TextMaterialVO)
					{	
						(mat as TextMaterialVO).width = getTextDimensions(clone3D).x;
						(mat as TextMaterialVO).height = getTextDimensions(clone3D).y;
										
						(clone3D as MaterialsListObject3DVO).selectedFace = (mat as TextMaterialVO).face;
						
						sendNotification(Notifications.UPDATE_OBJECT3D_MATERIAL_MODEL, clone3D);
					}
				}
			}
			
			var selectedMat:MaterialVO = (VO as MaterialsListObject3DVO).materialsList[(VO as MaterialsListObject3DVO).selectedFace]
			
			if(selectedMat is TextMaterialVO)
			{
				(selectedMat as TextMaterialVO).width = getTextDimensions(VO).x;
				(selectedMat as TextMaterialVO).height = getTextDimensions(VO).y;
			}
			// ensure selected face is the same as at beginning
			sendNotification(Notifications.UPDATE_OBJECT3D_MATERIAL_MODEL, VO);
		}
		
		protected function getTextDimensions(object3D:Object3DVO):Point
		{
			var dimensions:Point = new Point();
			
			if(object3D is PlaneVO)
			{
				dimensions.x = (object3D as PlaneVO).scaleX * (object3D as PlaneVO).width;
				dimensions.y = (object3D as PlaneVO).scaleY * (object3D as PlaneVO).height;		
			} 
			
			if(object3D is CubeVO)
			{	
				if((object3D as CubeVO).selectedFace == CubeVO.BACK_FACE || (object3D as CubeVO).selectedFace == CubeVO.FRONT_FACE)
				{
					dimensions.x = (object3D as CubeVO).scaleX * (object3D as CubeVO).width;
					dimensions.y = (object3D as CubeVO).scaleY * (object3D as CubeVO).height;
			
				}
				
				if((object3D as CubeVO).selectedFace == CubeVO.TOP_FACE || (object3D as CubeVO).selectedFace == CubeVO.BOTTOM_FACE)
				{
					dimensions.x = (object3D as CubeVO).scaleX * (object3D as CubeVO).width;
					dimensions.y = (object3D as CubeVO).scaleZ * (object3D as CubeVO).depth;
				
				}
				
				if((object3D as CubeVO).selectedFace == CubeVO.LEFT_FACE || (object3D as CubeVO).selectedFace == CubeVO.RIGHT_FACE)
				{
					dimensions.x = (object3D as CubeVO).scaleZ * (object3D as CubeVO).depth;
					dimensions.y = (object3D as CubeVO).scaleY * (object3D as CubeVO).height;
				}

			}
			
			return dimensions;
		}
		
		protected function handleDisplayFlatOnScreen(obj:Object):void
		{
			var VO:Object3DVO = settings.getObject3D(obj.name);
			var object3D:DisplayObject3D;
			var w:uint;
			var h:uint;
			
			if(VO is PlaneVO)
			{
				object3D = settings.scene.getChildByName(obj.name);
				
				w = (VO as PlaneVO).width * (VO as PlaneVO).scaleX;
				h = (VO as PlaneVO).height * (VO as PlaneVO).scaleY;
				
				if(obj.displayFlatOnScreen)
				{
					if(object3D is Plane)
					{
						settings.scene.removeChild(object3D);
		
						var billboard:BillBoard = new BillBoard((object3D as Plane).material, w, h);
						billboard.name = (object3D as Plane).name;
						billboard.copyTransform(object3D);
						
						settings.scene.addChild(billboard);
					}
				}else if(object3D is BillBoard)
				{
					settings.scene.removeChild(object3D);
							
					var plane:PlaneOutlined = new PlaneOutlined((object3D as BillBoard).material, w, h, (VO as PlaneVO).segmentsW, (VO as PlaneVO).segmentsH );
					plane.name = (object3D as Plane).name;
					plane.copyTransform(object3D);
					
					// reset rotations
					plane.rotationX = 0;
					plane.rotationY = 0;
					plane.rotationZ = 0;
					
					settings.scene.addChild(plane);
				}
			}
		}
	}
}